.data

# syscall constants
PRINT_INT = 1
PRINT_CHAR = 11
PRINT_STRING = 4

NULL = 0x0

# spimbot constants
VELOCITY = 0xffff0010
BOT_X = 0xffff0020
BOT_Y = 0xffff0024
ANGLE = 0xffff0014
ANGLE_CONTROL = 0xffff0018
TIMER = 0xffff001c
TIMER_MASK = 0x8000
TIMER_ACKNOWLEDGE = 0xffff006c
SCAN_X = 0xffff0050
SCAN_Y = 0xffff0054
SCAN_RADIUS = 0xffff0058
SCAN_ADDRESS = 0xffff005c
SCAN_MASK = 0x2000
SCAN_ACKNOWLEDGE = 0xffff0064

data = 0
left = 4
right = 8

index:      .word 0
state:      .word 0
radius:     .word 30
sorted_index:   .word -1
scan_result: .space 524288
scan_done:  .word 0

x_coords: .word -1:15
y_coords: .word -1:15
distances: .word -1:15

three:	.float	3.0
five:	.float	5.0
PI:	.float	3.141592
F180:	.float  180.0

.text

main:
    sub $sp, $sp, 12
    sw  $ra, 8($sp)
    
    sw  $zero, VELOCITY # stop the bot
    
    # enable interrupts
    li  $t0, SCAN_MASK      # scan interrupt enable bit
    or  $t0, $t0, 1     # global interrupt enable
    mtc0    $t0, $12        # set interrupt mask
    
    # scan whole map
    li  $a0, 150
    li  $a1, 150
    li  $a2, 213
    
    
    
    jal scan
    
    lw $a0, BOT_X
    lw $a1, BOT_Y
    la $a2, x_coords
    la $a3, y_coords
    
    la $t0, distances
    sw $t0, 0($sp)
    li $t5, 15
    sw $t5, 4($sp)
    
    jal iteratePath
    
    # will loop until there is something to decode

scanning:

    j scanning
    
    lw $ra, 0($sp)
    add $sp, $sp, 4

# scan #######################################################
#
# arguments $a0: center x (center of scan box!)
#           $a1: center y (center of scan box!)
#           $a2: radius
#

scan:
    
    # set center of scan and radius
    sw $a0, SCAN_X
    sw $a1, SCAN_Y
    sw $a2, SCAN_RADIUS
    
    # put result of scan in scan_result
    la $t0, scan_result
    sw $t0, SCAN_ADDRESS
    
    jr $ra


# selectSmallest #######################################################
#
# arguments $a0: array of (i.e. pointer to) integers
#           $a1: size of array
#

selectSmallest:
    lw  $t0, 0($a0)     # min_array = numbers[0]
    li  $v0, 0          # min_location = 0
    li  $t1, 1          # i = 1

smallest_for:
    bge $t1, $a1, smallest_swap # !(i < array_size)
    mul $t2, $t1, 4     # i * 4
    add $t2, $a0, $t2       # &numbers[i]
    lw  $t2, 0($t2)     # numbers[i]
    bge $t2, $t0, smallest_skip # !(numbers[i] < min_array)
    move    $v0, $t1        # min_location = i
    move    $t0, $t2        # min_array = numbers[i]

smallest_skip:
    add $t1, $t1, 1     # i++
    j   smallest_for

smallest_swap:
    lw  $t1, 0($a0)     # temp = numbers[0]
    sw  $t0, 0($a0)     # numbers[0] = min_array
    mul $t2, $v0, 4     # min_location * 4
    add $t2, $a0, $t2       # &numbers[min_location]
    sw  $t1, 0($t2)     # numbers[min_location] = temp
    jr  $ra         # return min_location (already in $v0)


# calculateDistance ####################################################
#
# arguments $a0:    x1 coordinate
#           $a1:    y1 coordinate
#           $a2:    array of x coordinates
#       $a3:    array of y coordinates
#           0($sp): array of distances (to be modified)
#           4($sp): size of array(s) 

calculateDistance:
    lw  $t0, 0($sp)     # distances
    lw  $t1, 4($sp)     # array_size
    li  $t2, 0          # i

distance_for:
    bge $t2, $t1, distance_done # !(i < array_size)
    mul $t3, $t2, 4     # i * 4

    add $t4, $a2, $t3       # &x_coords[i]
    lw  $t4, 0($t4)     # x_coords[i]
    sub $t4, $a0, $t4       # x1 - x_coords[i]
    abs $t4, $t4        # abs(x1 - x_coords[i])

    add $t5, $a3, $t3       # &y_coords[i]
    lw  $t5, 0($t5)     # y_coords[i]
    sub $t5, $a1, $t5       # y1 - y_coords[i]
    abs $t5, $t5        # abs(y1 - y_coords[i])

    add $t4, $t4, $t5       # abs(...) + abs(...)
    
    add $t3, $t0, $t3       # &distances[i]
    sw  $t4, 0($t3)     # distances[i] = abs(...) + abs(...)
    add $t2, $t2, 1     # i++
    j   distance_for

distance_done:
    jr  $ra


# calculatePath ########################################################
#
# arguments $a0:    spimbot x
#           $a1:    spimbot y
#           $a2:    array of x coordinates
#             $a3:    array of y coordinates
#           0($sp): array of distances (to be modified)
#           4($sp): size of array(s) 

.globl calculatePath
calculatePath:
    # wait to test for synchronization with interrupt handler
    li  $t0, 14000
path_wait:
    sub $t0, $t0, 1
    bge $t0, 0, path_wait

    lw  $t0, 0($sp)     # distances
    lw  $t1, 4($sp)     # array_size

    sub $sp, $sp, 20
    sw  $ra, 8($sp)
    sw  $a2, 12($sp)        # x_coords
    sw  $a3, 16($sp)        # y_coords

    sw  $t0, 0($sp)     # pass 5th argument on the stack
    sw  $t1, 4($sp)     # pass 6th argument on the stack
    jal calculateDistance   # $a registers already hold correct values

    lw  $a0, 20($sp)        # distances
    lw  $a1, 24($sp)        # array_size
    jal selectSmallest
    mul $v0, $v0, 4     # min_index * 4

    lw  $a2, 12($sp)        # x_coords
    lw  $t0, 0($a2)     # temp = x_coords[0]
    add $t1, $a2, $v0       # &x_coords[min_index]
    lw  $t2, 0($t1)     # x_coords[min_index]
    sw  $t2, 0($a2)     # x_coords[0] = x_coords[min_index]
    sw  $t0, 0($t1)     # x_coords[min_index] = temp

    lw  $a3, 16($sp)        # y_coords
    lw  $t0, 0($a3)     # temp = y_coords[0]
    add $t1, $a3, $v0       # &y_coords[min_index]
    lw  $t2, 0($t1)     # y_coords[min_index]
    sw  $t2, 0($a3)     # y_coords[0] = y_coords[min_index]
    sw  $t0, 0($t1)     # y_coords[min_index] = temp

    lw  $a0, 0($a2)
    jal print_int_and_space # print closest x_coord of this iteration
    lw  $a0, 0($a3)
    jal print_int_and_newline   # print closest y_coord of this iteration

    lw  $ra, 8($sp)
    add $sp, $sp, 20
    jr  $ra



# print int and space ##################################################
#
# argument $a0: number to print

print_int_and_space:
    li  $v0, PRINT_INT  # load the syscall option for printing ints
    syscall         # print the number

    li  $a0, ' '    # print a blank space
    li  $v0, PRINT_CHAR # load the syscall option for printing chars
    syscall         # print the char
    
    jr  $ra     # return to the calling procedure


# print int and new line ##################################################
#
# argument $a0: number to print

print_int_and_newline:
    li  $v0, PRINT_INT  # load the syscall option for printing ints
    syscall         # print the number

    li  $a0, '\n'   # print a new line character
    li  $v0, PRINT_CHAR # load the syscall option for printing chars
    syscall         # print the char
    
    jr  $ra     # return to the calling procedure
    
    
################################################################
# delete_node - deletes a node from the tree
# $a0 - a double pointer to the node to be deleted
# don't worry about deallocating memory - consider a node to be
# deleted if nothing points to it
# consider this a helper function for remove_value
################################################################

.globl delete_node
delete_node:
    lw  $t0, ($a0)      # *to_delete
    lw  $t1, left($t0)      # (*to_delete)->left
    lw  $t2, right($t0)     # (*to_delete)->right

    bne $t1, NULL, dn_right # !((*to_delete)->left == NULL)
    sw  $t2, ($a0)      # *to_delete = (*to_delete)->right
    jr  $ra

dn_right:
    bne $t2, NULL, dn_iop   # !((*to_delete)->right == NULL)
    sw  $t1, ($a0)      # *to_delete = (*to_delete)->left
    jr  $ra

dn_iop:
    la  $a0, left($t0)      # temp = &((*to_delete)->left)

dn_iop_loop:
    lw  $t1, ($a0)      # *temp
    lw  $t2, right($t1)     # (*temp)->right
    beq $t2, NULL, dn_iop_found # !((*temp)->right != NULL)
    la  $a0, right($t1)     # temp = &((*temp)->right)
    j   dn_iop_loop

dn_iop_found:
    lw  $t1, data($t1)      # (*temp)->data
    sw  $t1, data($t0)      # (*to_delete)->data = (*temp)->data
    j   delete_node     # yet another tail call


################################################################
# remove_value - removes a value from the tree
# $a0 - a double pointer to the root of the tree
# $a1 - the value to be removed
# this should find the node containing the value we want to
# remove, and then call delete_node
################################################################

.globl remove_value
remove_value:
    lw  $t0, ($a0)      # *root
    bne $t0, NULL, rv_not_null  # !(*root == NULL)
    jr  $ra

rv_not_null:
    lw  $t1, data($t0)      # (*root)->data
    bne $t1, $a1, rv_find_node  # !((*root)->data == x)
    j   delete_node     # and another tail call

rv_find_node:
    ble $t1, $a1, rv_go_right   # !((*root)->data > x)
    la  $a0, left($t0)      # &((*root)->left)
    j   remove_value        # and another one

rv_go_right:
    la  $a0, right($t0)     # &((*root)->right)
    j   remove_value        # and one more


# iteratePath ########################################################
#
# arguments: $a0:    spimbot x
#            $a1:    spimbot y
#            $a2:    x_coords[]
#            $a3:    y_coords[]
#            0($sp): array of distances (to be modified)
#            4($sp): size of array(s)

.globl iteratePath
iteratePath:
    
    la $t1, scan_done

    wait_for_tokens:
    lw $t0, 0($t1)
    beq $t0, 0, wait_for_tokens
     
    sub $sp, $sp, 40
    sw  $ra, 8($sp)
    sw  $s0, 12($sp)
    sw  $s1, 16($sp)
    sw  $s2, 20($sp)
    sw  $s3, 24($sp)
    sw  $s4, 28($sp)
    sw  $s5, 32($sp)
    sw  $s6, 36($sp)
    
    jal process_trees
    
    lw $a0, BOT_X
    lw $a1, BOT_Y

    li  $t0, TIMER_MASK     # timer interrupt enable bit
    or  $t0, $t0, 1     # global interrupt enable
    mtc0    $t0, $12        # enable_timer_interrupts()

    lw  $t0, TIMER      # get_timer()
    add $t0, $t0, 100       # get_timer() + 100
    sw  $t0, TIMER      # set_timer(...)

    move    $s0, $a2        # x_coords
    move    $s1, $a3        # y_coords
    lw  $s2, 40($sp)        # distances
    lw  $s3, 44($sp)        # array_size
    li  $s4, 0          # i = 0

ip_loop:
    bge $s4, $s3, ip_end    # !(i < array_size)

    mul $t0, $s4, 4     # i * 4
    add $s5, $s0, $t0       # &x_coords[i]
    move    $a2, $s5
    add $s6, $s1, $t0       # &y_coords[i]
    move    $a3, $s6
    add $t0, $s2, $t0       # &distances[i]
    sw  $t0, 0($sp)     # pass 5th argument on stack
    sub $t0, $s3, $s4       # array_size - i
    sw  $t0, 4($sp)     # pass 6th argument on stack
    jal calculatePath       # $a0 and $a1 already hold correct values

    lw  $a0, 0($s5)     # x1 = x_coords[i]
    lw  $a1, 0($s6)     # y1 = y_coords[i]
    sw  $s4, sorted_index   # sorted_index = i
    add $s4, $s4, 1     # i++
    j   ip_loop

ip_end:
    lw  $ra, 8($sp)
    lw  $s0, 12($sp)
    lw  $s1, 16($sp)
    lw  $s2, 20($sp)
    lw  $s3, 24($sp)
    lw  $s4, 28($sp)
    lw  $s5, 32($sp)
    lw  $s6, 36($sp)
    add $sp, $sp, 40
    jr  $ra


# remove_common_values ########################################################
#
# arguments: $a0:    node_t * source_root
#            $a1:    node ** target_root


remove_common_values:
    bne    $a0, $0, rest_remove_common_values       # checking if(source-rot == null)
    jr     $ra

rest_remove_common_values:        
    sub    $sp, $sp, 12                             # allocate stack space 
    sw     $ra, 0($sp)                              # save $ra on the stack
    sw     $a0, 4($sp)                              # ...
    sw     $a1, 8($sp)                              # ...
    
    lw     $a0, 4($a0)                              # loading address of source_root->left
    
    jal    remove_common_values                     # calling remove_common_values(source_root->left, target_root)
    
    lw     $a0, 4($sp)                              # reload source_root in $a0
    lw     $a1, 0($a0)                              # loading source_root->data in $a1
    lw     $a0, 8($sp)                              # loading target_root in $a0
    
    jal    remove_value                             # calling remove_value(target_root, source_root->data)
    
    lw     $a0, 4($sp)                              # loading source_root in $a0
    lw     $a0, 8($a0)                              # loading source_root->right in $a0 for the next method
    lw     $a1, 8($sp)                              # loading target_root in $a1
    
    jal    remove_common_values                     # calling remove_common_values(source_root->right, target_root)
    
    lw     $ra, 0($sp)                              # reload $ra from the stack
    add    $sp, $sp, 12                             # free space on the stack
    
    jr     $ra                                      # return from the method remove_common_values                                      


# compute_coordinates ########################################################
#
# arguments: $a0:    node_t * root
#            $a1:    int * coordinates
.globl compute_coordinates
compute_coordinates:
    bne    $a0, $0, rest_compute_coordinates        # checking if(root == null)
    jr     $ra                                      # return from method
    
rest_compute_coordinates:
    sub    $sp, $sp, 12                             # create stack frame 
    sw     $ra, 0($sp)                              # save $ra on the stack
    sw     $a0, 4($sp)                              # ...
    sw     $a1, 8($sp)                              # ...
    
    lw     $a0, 4($a0)                              # loading address of source_root->left
    
    jal    compute_coordinates                      # calling compute_coordinates(source_root->left, coordinates)
    
    lw     $a0, 8($sp)                              # loading coordinates pointer into $t0
    lw     $t0, 0($a0)                              # laoding values of *coordinates in $t0
    sll    $t0, $t0, 1                              # implementing (*coordinates << 1)
    
    lw     $t1, 4($sp)                              # loading root in $t1
    lw     $t1, 0($t1)                              # loading value of root->data in $t1
    andi   $t1, $t1, 1                              # implementing (root->data & 1)
    
    or     $a1, $t0, $t1                            # implementing (*coordinates = (*coordinates << 1) | (root->data & 1))
    
    move $t9, $a0
    
    move $a0, $t9
    
    sw     $a1, 0($a0)
    move   $a1, $a0
    lw     $a0, 4($sp)                              # laoding the original $a0 from the stack into $a0
    lw     $a0, 8($a0)                              # loading root->right in $a0
    
    jal    compute_coordinates                      # calling compute_coordinates(root->right, coordinates)
    
    lw     $ra, 0($sp)                              # reload $ra from the stack
    add    $sp, $sp, 12                             # free stack space
    
    jr     $ra                                      # return from the method remove_common_values
    
# process_trees ########################################################
#
# arguments: 
#
process_trees:

    la $a0, scan_result                                                       # $a0 = pointer to result trees_t struct
    lw $t0, 0($a0)                                                            # get num_tokens
    #sll $t0, $t0, 1                                                           # #t0 = num trees  
    li $t2, 0                                                                 # $t2 = i = 0
    
    sub $sp, $sp, 20
    sw $ra, 0($sp)
    sw $t0, 4($sp)                                                            # save num trees
    sw $t2, 8($sp)                                                            # save i
    # 20($sp) is coordinates

    
process_trees_for:
    #move $a0, $t2
    
    #jal print_int_and_newline
    
    lw $t0, 4($sp)                                                            # load numtrees
    
    bge $t2, $t0, end_process_trees_for                                       # end loop if i >= num trees
    
    la $a0, scan_result                                                       # $a0 = pointer to result trees_t struct
    add $a0, $a0, 4
    
    sll $t1, $t2, 3                                                           # $t1 = (i*2)*4
    add $a0, $a0, $t1                                                         # $a0 = &roots[i * 2]
    add $a1, $a0, 4                                                           # $a1 = &roots[i * 2 + 1] for remove_common_values
    lw $a0, 0($a0)                                                            # $a0 = roots[i * 2] for remove_common_values
    
    sw $a1, 12($sp)                                                            # save &roots[i * 2 + 1] for later use
    
    jal remove_common_values
    
    sw $0, 16($sp)                                                            # coordinates = 0 
    add $a1, $sp, 16                                                          # $a1 = &coordinates for compute_coordinates
    
    lw $a0, 12($sp)                                                           # $a0 = &roots[i * 2 + 1]
    lw $a0, 0($a0)                                                            # $a0 = roots[i * 2 + 1] for compute_coordinates
    
    jal compute_coordinates
    
    lw $t2, 8($sp)                                                            # $t2 = i
    sll $t1, $t2, 2                                                           # $t1 = i*4
    
    la $a0, x_coords                                                          # $a0 = x_coords
    la $a1, y_coords                                                          # $a1 = y_coords
    
    add $a0, $a0, $t1                                                         # $a0 = &x[i]
    add $a1, $a1, $t1                                                         # $a0 = &x[i]
    
    lw $t0, 16($sp)
    #lw $t0, coordinates                                                       # $t0 = coordinates
    
    srl $t1, $t0, 16                                                          # $t1 = coordinates >> 16
    and $t1, $t1, 0xffff                                                      # $t1 = coordinates >> 16 & 0xffff
    
    and $t2, $t0, 0xffff                                                      # $t2 = coordinates & 0xffff
    
    sw $t1, 0($a0)                                                            # set x[i] and y[i]
    sw $t2, 0($a1)
    
    li $a0, 11111111
    jal print_int_and_space 
    move  $a0, $t1
    jal print_int_and_space 
    move  $a0, $t2
    jal print_int_and_newline

    
    lw $t2, 8($sp)                                                            # load i from memory
    
    add $t2, $t2, 1
    
    sw $t2, 8($sp)                                                            # save i to mem
    
    j process_trees_for
        
end_process_trees_for:
    
    lw $ra, 0($sp)
    add $sp, $sp, 20
    jr $ra
    
.kdata
interrupt_space:    .word 0:2
interrupt_vars:    .word 0:2
coordinates:        .word 0
save0: .word 0
save1: .word 0
non_intrpt_str: .asciiz "Non-interrupt exception\n"
unhandled_str:  .asciiz "Unhandled interrupt type\n"

.ktext 0x80000180
interrupt_handler:
    .set noat
    move    $k1, $at        # Save $at
    .set at
    sw  $a0, save0      # Get some free registers
    sw  $v0, save1      # by storing them to global variables

    mfc0    $k0, $13        # Get Cause register
    srl     $a0, $k0, 2     
    and     $a0, $a0, 0xf       # ExcCode field
    bne     $a0, 0, non_intrpt

interrupt_dispatch:         # Interrupt:
    mfc0    $k0, $13        # Get Cause register, again
    beq $k0, 0, done        # handled all outstanding interrupts

    and $a0, $k0, TIMER_MASK    # is there a timer interrupt?
    bne $a0, 0, timer_interrupt
    
    and $a0, $k0, SCAN_MASK # is there a scan interrupt?
    bne $a0, 0, scan_interrupt

    li  $v0, PRINT_STRING   # Unhandled interrupt types
    la  $a0, unhandled_str
    syscall
    j   done
    
scan_interrupt:
    
    sw  $a0, SCAN_ACKNOWLEDGE
    
    li $a0, 1
    la $v0, scan_done
    sw $a0, 0($v0)
    
    j	interrupt_dispatch

timer_interrupt:
    sw  $a0, TIMER_ACKNOWLEDGE  				# acknowledge_timer_interrupt()

ti_loop:
    lw  $a0, sorted_index
    lw  $v0, index
    bge $a0, $v0, ti_align  					# !(sorted_index < index)

    sw  $0, VELOCITY        					# set_velocity(0)
    lw  $a0, TIMER      						# get_timer()
    add $a0, $a0, 400       					# get_timer() + 400
    sw  $a0, TIMER      						# set_timer(...)
    j   interrupt_dispatch  					# return

ti_align:
    mul $k0, $v0, 4     						# index * 4
    lw  $a0, state
    bne $a0, 0, ti_align_y  					# !(state == 0)

    lw  $a0, BOT_X      						# current_x
    lw  $k0, x_coords($k0)     					# target_x
    sub $k0, $k0, $a0       					# diff
    abs $a0, $k0        						# abs_diff
    bge $a0, 2, ti_face_x   					# !(abs_diff < 2)

    li  $a0, 1
    sw  $a0, state     							# state = 1
    j   ti_loop         						# continue

ti_face_x:
    ble $k0, 0, ti_face_left    				# !(diff > 0)
    li  $v0, 0          						# new_angle = 0
    j   ti_move         						# break

ti_face_left:
    li  $v0, 180        						# new_angle = 180
    j   ti_move         						# break

ti_align_y:
    lw  $a0, BOT_Y      						# current_y
    lw  $k0, y_coords($k0)     					# target_y
    sub $k0, $k0, $a0       					# diff
    abs $a0, $k0        						# abs_diff
    bge $a0, 2, ti_face_y   					# !(abs_diff < 2)

    sw  $zero, state        					# state = 0
    add $v0, $v0, 1     						# index + 1
    sw  $v0, index      						# index = index + 1
    j   ti_loop         						# continue

ti_face_y:
    ble $k0, 0, ti_face_up  					# !(diff > 0)
    li  $v0, 90         						# new_angle = 90
    j   ti_move         						# break

ti_face_up:
    li  $v0, 270        						# new_angle = 270

ti_move:
    sw  $v0, ANGLE      						# new_angle
    li  $v0, 1
    sw  $v0, ANGLE_CONTROL  					# set_absolute_angle(new_angle)
    li  $v0, 10
    sw  $v0, VELOCITY       					# set_velocity(10)
    lw  $v0, TIMER      						# get_timer()
    mul $a0, $a0, 400       					# abs_diff * 400
    add $v0, $v0, $a0       					# get_timer() + abs_diff * 400
    sw  $v0, TIMER      						# set_timer(...)
    j   interrupt_dispatch

# -----------------------------------------------------------------------
# sb_arctan - computes the arctangent of y / x
# $a0 - x
# $a1 - y
# returns the arctangent
# -----------------------------------------------------------------------


sb_arctan:
    li  $v0, 0      # angle = 0;

    abs $t0, $a0    # get absolute values
    abs $t1, $a1
    ble $t1, $t0, no_TURN_90      

    ## if (abs(y) > abs(x)) { rotate 90 degrees }
    move    $t0, $a1    # int temp = y;
    sub $a1, $zero, $a0 # y = -x;      
    move    $a0, $t0    # x = temp;    
    li  $v0, 90     # angle = 90;  

no_TURN_90:
    bge $a0, $zero, pos_x   # skip if (x >= 0)

    ## if (x < 0) 
    add $v0, $v0, 180   # angle += 180;

pos_x:
    mtc1    $a0, $f0
    mtc1    $a1, $f1
    cvt.s.w $f0, $f0    # convert from ints to floats
    cvt.s.w $f1, $f1
    
    div.s   $f0, $f1, $f0   # float v = (float) y / (float) x;

    mul.s   $f1, $f0, $f0   # v^^2
    mul.s   $f2, $f1, $f0   # v^^3
    l.s $f3, three($zero)   # load 5.0
    div.s   $f3, $f2, $f3   # v^^3/3
    sub.s   $f6, $f0, $f3   # v - v^^3/3

    mul.s   $f4, $f1, $f2   # v^^5
    l.s $f5, five($zero)    # load 3.0
    div.s   $f5, $f4, $f5   # v^^5/5
    add.s   $f6, $f6, $f5   # value = v - v^^3/3 + v^^5/5

    l.s $f8, PI($zero)      # load PI
    div.s   $f6, $f6, $f8   # value / PI
    l.s $f7, F180($zero)    # load 180.0
    mul.s   $f6, $f6, $f7   # 180.0 * value / PI

    cvt.w.s $f6, $f6    # convert "delta" back to integer
    mfc1    $t0, $f6
    add $v0, $v0, $t0   # angle += delta

    jr  $ra

non_intrpt:             # was some non-interrupt
    li  $v0, PRINT_STRING           
    la  $a0, non_intrpt_str
    syscall             # print out an error message
    j   done

done:
    lw  $a0, save0
    lw  $v0, save1
    .set noat
    move    $at, $k1        # Restore $at
    .set at
    eret
